#include "app_mqtt.h"
#include "log/log.h"
#include <MQTTClient.h>
#include <string.h>

static MQTTClient_message pubmsg = MQTTClient_message_initializer;
static MQTTClient client;
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
static int (*recv_callback)(char *json) = NULL;
// 消息发送成功回调函数
static void delivered(void *context, MQTTClient_deliveryToken dt)
{
    log_debug("消息发送成功！");
}

// 收到远程消息回调函数
// 注意：返回1表示消息处理成功，返回0表示消息处理失败
static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int result = 0;
    // 步骤1：检查是否已注册回调
    if (recv_callback)
    {
        // 如果函数返回值为0,msgarrvd（）函数返回1；如果函数返回值为非0，msgarrvd（）函数返回0
        //  步骤2：调用外部回调函数，并转换返回值
        result = recv_callback((char *)message->payload) == 0 ? 1 : 0;
    }
    // 步骤3：释放资源
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    // 步骤4：返回结果给MQTT库
    return result;
}

// 连接断开回调函数
static void connlost(void *context, char *cause)
{
    log_error("MQTT连接断开,原因:%s", cause);
}

/**
 * 初始化MQTT客户端
 */
int app_mqtt_init()
{
    // 初始化客户端
    if (MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_error("创建MQTT客户端失败");
        return -1;
    }

    // 设置回调函数
    if (MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered) != MQTTCLIENT_SUCCESS)
    {
        log_error("设置MQTT回调函数失败");
        MQTTClient_destroy(&client);
        return -1;
    }

    // 连接MQTT服务器
    if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS)
    {
        log_error("连接MQTT服务器失败");
        MQTTClient_destroy(&client);
        return -1;
    }

    // 订阅主题
    if (MQTTClient_subscribe(client, TOPIC_R2G, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_error("订阅主题失败");
        app_mqtt_close();
        return -1;
    }
    log_info("MQTT客户端初始化成功");

    return 0;
}

/**
 * 关闭MQTT客户端
 */
int app_mqtt_close()
{
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
}

/**
 * 发送消息给远程服务器
 */
int app_mqtt_send(char *json)
{
    pubmsg.payload = json;
    pubmsg.payloadlen = strlen(json) + 1;
    pubmsg.qos = QOS;

    if (MQTTClient_publishMessage(client, TOPIC_G2R, &pubmsg, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_error("发送消息失败");
        return -1;
    }
    log_debug("发送消息成功:%s", json);
    return 0;
}

/**
 * 注册接收处理远程消息的函数
 *
 *
 * 将msgarrvd()函数里的数据交给其他模块->外部其他模块传入一个回调函数进来，存起来->受到消息，调用回调函数
 */
void app_mqtt_registerRecvCallback(int (*callback)(char *json))
{
    recv_callback = callback;
}



/*
1.检查回调是否注册

如果 recv_callback 为 NULL，跳过处理，直接释放资源并返回 0（表示未处理）。

如果已注册（recv_callback != NULL），继续执行。

2.调用外部回调函数

将 message->payload（消息内容）传递给外部回调函数 recv_callback。

返回值转换：

外部回调返回 0 → msgarrvd() 返回 1（告诉MQTT库消息处理成功）。

外部回调返回非 0 → msgarrvd() 返回 0（告诉MQTT库消息处理失败）。

3.释放资源

调用 MQTTClient_freeMessage 和 MQTTClient_free 释放MQTT库分配的内存，避免泄漏。

4.返回处理结果

返回值 1 或 0 会传递给MQTT库，可能影响库的重试机制或日志记录（具体行为取决于MQTT实现）。




假设外部模块注册了回调并收到一条消息：

程序启动：recv_callback 初始化为 NULL。

注册回调：外部调用 app_mqtt_registerRecvCallback(my_callback)，此时 recv_callback = my_callback。

MQTT消息到达：

MQTT库调用 msgarrvd(context, "topic", 5, message)。

msgarrvd 检查 recv_callback 非空，调用 my_callback(message->payload)。

若 my_callback 返回 0，msgarrvd 返回 1。

释放 message 和 topicName 内存。

MQTT库：根据返回值 1 认为消息处理成功。

*/